package utils

import (
	"fmt"
	"time"

	"github.com/hashicorp/consul/api"
)

// ConsulClient Consul客户端封装
type ConsulClient struct {
	client *api.Client
}

// NewConsulClient 创建新的Consul客户端
func NewConsulClient(address string) (*ConsulClient, error) {
	config := api.DefaultConfig()
	if address != "" {
		config.Address = address
	}

	client, err := api.NewClient(config)
	if err != nil {
		return nil, fmt.Errorf("创建Consul客户端失败: %w", err)
	}

	return &ConsulClient{client: client}, nil
}

// RegisterService 注册服务到Consul
func (cc *ConsulClient) RegisterService(serviceID, serviceName, address string, port int, tags []string) error {
	registration := &api.AgentServiceRegistration{
		ID:      serviceID,
		Name:    serviceName,
		Address: address,
		Port:    port,
		Tags:    tags,
		Check: &api.AgentServiceCheck{
			HTTP:                           fmt.Sprintf("http://%s:%d/health", address, port),
			Timeout:                        "3s",
			Interval:                       "10s",
			DeregisterCriticalServiceAfter: "30s",
		},
	}

	if err := cc.client.Agent().ServiceRegister(registration); err != nil {
		return fmt.Errorf("注册服务失败: %w", err)
	}

	return nil
}

// DeregisterService 从Consul注销服务
func (cc *ConsulClient) DeregisterService(serviceID string) error {
	if err := cc.client.Agent().ServiceDeregister(serviceID); err != nil {
		return fmt.Errorf("注销服务失败: %w", err)
	}
	return nil
}

// GetService 获取服务信息
func (cc *ConsulClient) GetService(serviceID string) (*api.AgentService, error) {
	services, err := cc.client.Agent().Services()
	if err != nil {
		return nil, fmt.Errorf("获取服务列表失败: %w", err)
	}

	service, exists := services[serviceID]
	if !exists {
		return nil, fmt.Errorf("服务不存在: %s", serviceID)
	}

	return service, nil
}

// GetAllServices 获取所有服务
func (cc *ConsulClient) GetAllServices() (map[string]*api.AgentService, error) {
	services, err := cc.client.Agent().Services()
	if err != nil {
		return nil, fmt.Errorf("获取服务列表失败: %w", err)
	}
	return services, nil
}

// HealthCheck 检查服务健康状态
func (cc *ConsulClient) HealthCheck(serviceID string) (bool, error) {
	checks, err := cc.client.Agent().Checks()
	if err != nil {
		return false, fmt.Errorf("获取健康检查失败: %w", err)
	}

	for _, check := range checks {
		if check.ServiceID == serviceID {
			return check.Status == "passing", nil
		}
	}

	return false, fmt.Errorf("未找到服务的健康检查: %s", serviceID)
}

// ServiceHealth 服务健康状态结构
type ServiceHealth struct {
	ServiceID   string    `json:"service_id"`
	ServiceName string    `json:"service_name"`
	Status      string    `json:"status"` // passing, warning, critical
	LastCheck   time.Time `json:"last_check"`
	Output      string    `json:"output,omitempty"`
}

// GetServiceHealths 获取所有服务的健康状态
func (cc *ConsulClient) GetServiceHealths() ([]ServiceHealth, error) {
	checks, err := cc.client.Agent().Checks()
	if err != nil {
		return nil, fmt.Errorf("获取健康检查失败: %w", err)
	}

	services, err := cc.client.Agent().Services()
	if err != nil {
		return nil, fmt.Errorf("获取服务列表失败: %w", err)
	}

	var healths []ServiceHealth
	for _, check := range checks {
		if check.ServiceID == "" {
			continue // 跳过非服务检查
		}

		service, exists := services[check.ServiceID]
		var serviceName string
		if exists {
			serviceName = service.Service
		} else {
			serviceName = check.ServiceID
		}

		health := ServiceHealth{
			ServiceID:   check.ServiceID,
			ServiceName: serviceName,
			Status:      check.Status,
			Output:      check.Output,
		}

		healths = append(healths, health)
	}

	return healths, nil
}
